#include <kutils.h>
#include <string.h>
#include "apm.h"
#include "memory.h"
#include "vfs.h"
#include "display.h"

void init_apm(void)
{
#ifdef FLUIDIUM_DEBUG
	write_string("APM: Init\n");
#endif
	//load the apm module off of the filesystem
	fs_node_t* file = open_fs("/packages/kernel/apmdvr.o");
	if(file)
	{
		u8int *file_buffer = (u8int*)kmalloc(file->length);
		if(read_fs(file, file->length, file_buffer))
		{
			//we now have a pos32inter to the file's contents in file_buffer
			u32int *apm_dest = (u32int*)0x1000;
			memset(apm_dest, 0, (size_t)file->length);
			memcpy(apm_dest, file_buffer, (size_t)file->length);
		}
		else
		{
			write_string("APM: module could not be read.\n");
		}
		if(!close_fs(file))
		{
			write_string("APM: module could not be closed.\n");
		}
		kfree(file_buffer);
	}
	else
	{//file could not be opened
		write_string("APM: module could not be opened.\n");
		return;
	}
}

void apm_reboot(void)
{
	disable_interrupts();

	//wait for the keyboard buffer to flush
	unsigned temp;
	do
	{
		temp = inportb(0x64);
		if((temp & 0x01) != 0)
		{
			(void)inportb(0x60);
			continue;
		}
	} while((temp & 0x02) != 0);
	//pulse the cpu reset line
	outportb(0x64, 0xFE);

	halt();
}

void apm_shutdown(void)
{
	enable_scroll();

	u32int auto_powerdown = 0;
	u32int error = 0;
	u32int data_safe = 1;
	s8int *m1 = "Shutting Down";
	clear_screen();
	set_cursor(0,0);
	set_cursor((u32int)((40 - (strlen(m1) / 2)) - 4), 1);
	settextcolor(9,0);	
	write_string("... ");
	settextcolor(15,0);
	write_string(m1);
	settextcolor(9,0);
	write_string(" ...\n\n");

	// the actual shutdown routines should go here
	settextcolor(VGA_WHITE,0);
	write_string("APM: Verifying the shutdown module...\n");
	if(*((u32int*)0x1000) != 0x900DF00D)
	{
		settextcolor(VGA_RED,0);	
		write_string("APM: Invalid shutdown module signature.\n");
		settextcolor(VGA_WHITE,0);
		auto_powerdown = 0;
	}
	else
	{
		auto_powerdown = 1;
	}
	
	if(!data_safe)
		error = 1;//force an error if the data is not safe
	if(!auto_powerdown)
		error = 1;
	
	if(error)
	{
		write_string("\nThere were one or more errors during the shutdown process.\n");
		if(data_safe)
		{
			write_string("Your data is safe ");
			if(auto_powerdown)
			{
				write_string("and Fluidium will now attempt to \npower-down the computer automatically.\n");
				write_string("If it doesn't work:\n");
				write_string("    1. An error code may appear in the top left corner of the screen.\n");
				write_string("    2. Know that it is safe to press the power button.\n");
				disable_interrupts();
				asm_shutdown();	
			}
			else
			{
				write_string("but Fluidium is not able to \npower-down the computer automatically.\n\n");
				write_string("It is safe to press the power button.\n");
				halt();
			}
		}
		else
		{
			write_string("Your data might be corrupted if you press the power button now.\n");
			write_string("In this situation it is best to wait for about 30 seconds to allow the drive to write it's caches to the disk. ");
			write_string("Then it is ok to press the power button.\n");
			halt();
		}
	}
	else
	{
		write_string("\nNo errors were reported during the shutdown process.\n");
		write_string("Fluidium will now attempt to power-down the computer automatically.\n");
		write_string("If it doesn't work:\n");
		write_string("    1. An error code may appear in the top left corner of the screen.\n");
		write_string("    2. Know that it is safe to press the power button.\n");
		disable_interrupts();
		asm_shutdown();	
	}
}
